/******************************************************************************
//             INTEL CORPORATION PROPRIETARY INFORMATION
//  This software is supplied under the terms of a license agreement or
//  nondisclosure agreement with Intel Corporation and may not be copied
//  or disclosed except in accordance with the terms of that agreement.
//        Copyright (c) 2000-2001 Intel Corporation. All Rights Reserved.
//
//  Description:
//      Intel(R) JPEG library for X platform 
//
********************************************************************************/
#include "_ijx.h"

extern Ipp16s _DefLumQuantTable[64];
extern Ipp16s _DefChromQuantTable[64];
extern Ipp8u  _DefLumDCHuffBits[];
extern Ipp8u  _DefLumDCHuffValues[];
extern Ipp8u  _DefChromDCHuffBits[];
extern Ipp8u  _DefChromDCHuffValues[];
extern Ipp8u  _DefLumACHuffBits[];
extern Ipp8u  _DefLumACHuffValues[];
extern Ipp8u  _DefChromACHuffBits[];
extern Ipp8u  _DefChromACHuffValues[];


/******************************************************************************
// Name:            ijAdjustMCUBufferInv_1
// Description:     Adjust MCU buffer for 1 component
//
// Input Arguments:
//        pMCUSpec:  Points to IJMCUSPEC structure 
// Output Arguments:
//      pIJXBuffer:  Points to IJBUFFER structure
//                          
//                  
******************************************************************************/
void ijAdjustMCUBufferInv_1 (IJMCUSPEC *pMCUSpec,
                             IJBUFFER  *pIJXBuffer)
{
    pIJXBuffer->paImgCoeffBufCur[0]+=pMCUSpec->naCoeffOffset[0];
}


/******************************************************************************
// Name:            ijAdjustMCUBufferInv_3
// Description:     Adjust MCU buffer for 3 component
//
// Input Arguments:
//        pMCUSpec:  Points to IJMCUSPEC structure 
// Output Arguments:
//      pIJXBuffer:  Points to IJBUFFER structure
//
//                  
******************************************************************************/
void ijAdjustMCUBufferInv_3 (IJMCUSPEC   *pMCUSpec,
                             IJBUFFER *pIJXBuffer)
{
    pIJXBuffer->paImgCoeffBufCur[0]+=pMCUSpec->naCoeffOffset[0];
    pIJXBuffer->paImgCoeffBufCur[1]+=pMCUSpec->naCoeffOffset[1];
    pIJXBuffer->paImgCoeffBufCur[2]+=pMCUSpec->naCoeffOffset[2];
}

/******************************************************************************
// Name:            ijParseApp0
// Description:     Parse App0 marker
// Input Arguments:
//         pStream: Identifies IJBITTREAMSTATE data structure.
// Output Arguments:
//    pDecodeState: Identifies IJDECODESTATE strcuture.
//                          
// Returns:          
//        [Success] IJX_RTCODE_OK
//        [Failure] IJX_RTCODE_BAGARG
//                  IJX_RTCODE_F_INSUFFICIENTBUF
//                  IJX_RTCODE_E_ERRPARAM
//                  IJX_RTCODE_F_NOTSUPPORTEDIDENT   
//                  
******************************************************************************/
IJXRESULT ijParseApp0(IJBITTREAMSTATE *pStream,
                      IJDECODESTATE *pDecodeState)
{
    int nClass=0;
    int nLen=0;
    IJXRESULT rtCode;
    rtCode=ijRead_APP0Class(&nClass,&nLen,pStream);
    if (!IJX_SUCCEEDED(rtCode)){
        return rtCode;
    }

    switch (nClass) {
        case 0:    // JFIF
            {
                IJAPP0_JFIF jfifApp0;
                rtCode=ijRead_APP0_JFIF(&nLen,
                                        &jfifApp0,
                                        pStream);
                if (!IJX_SUCCEEDED(rtCode)){
                    return rtCode;
                }
                pDecodeState->imageSpec.nDensityUnit=jfifApp0.Units;
                pDecodeState->imageSpec.nXDensity=jfifApp0.Xdpu;
                pDecodeState->imageSpec.nYDensity=jfifApp0.Ydpu;
                IJSEEKSTREAM(nLen, pStream);
                pDecodeState->nStatus|=IJX_STATUS_APP0;
            }
            break;
        case 1:   //JFXX
            IJSEEKSTREAM(nLen, pStream);
            break;
        case 2:   //IJXM 
            {
                rtCode=ijRead_APP0_IJXM(nLen,
                                        &(pDecodeState->nJPEGCodeMode),
                                        &(pDecodeState->imageSpec), 
                                        &(pDecodeState->waveSpec), 
                                        &(pDecodeState->motionSpec), 
                                        pStream);
                if (!IJX_SUCCEEDED(rtCode)){
                    return rtCode;
                }
            }
            break;
        default:
            IJSEEKSTREAM(nLen, pStream);
            return IJX_RTCODE_W_NOTSUPPORTEDIDENT;
    }
    return IJX_RTCODE_OK;
}

/******************************************************************************
// Name:            ijReadFrame
// Description:     Parse head info of JPEG
// Input Arguments:
//         pStream: Identifies IJBITTREAMSTATE data structure.
// Output Arguments:
//     pNextMarker: Identifies the value of the next marker.
//    pDecodeState: Identifies IJDECODESTATE strcuture.
//                          
// Returns:          
//        [Success] IJX_RTCODE_OK
//        [Failure] IJX_RTCODE_BAGARG
//                  IJX_RTCODE_ERROR
//                  IJX_RTCODE_F_INSUFFICIENTBUF
//                  IJX_RTCODE_E_ERRPARAM
//                  IJX_RTCODE_F_NOTSUPPORTEDIDENT   
//                  IJX_RTCODE_F_NOTSUPPORTEDMARKER
//                  IJX_RTCODE_E_NOTSUPPORTEDMARKER
//                  
******************************************************************************/
IJXRESULT ijReadFrame(IJBITTREAMSTATE *pStream,
                      IJDECODESTATE *pDecodeState)
{
    IJXRESULT rtCode;
    rtCode=ijParseTablesMisc(pStream, pDecodeState);

    if (!IJX_SUCCEEDED(rtCode)) {
        return rtCode;
    }

    pDecodeState->nDesiredMarker=IJX_MARKER_SOF;

    if (IJX_RTCODE_S_EOF==rtCode) {
       return IJX_RTCODE_S_EOF;
    }

    rtCode=ijPreprocessMarker(pStream, pDecodeState);
    if (!IJX_SUCCEEDED(rtCode)) {
        return rtCode;
    }

    return IJX_RTCODE_OK;
}

/******************************************************************************
// Name:            ijParseTablesMisc
// Description:     Parse head info of JPEG
// Input Arguments:
//         pStream: Identifies IJBITTREAMSTATE data structure.
// Output Arguments:
//     pNextMarker: Identifies the value of the next marker.
//    pDecodeState: Identifies IJDECODESTATE strcuture.
//                          
// Returns:          
//        [Success] IJX_RTCODE_OK
//        [Failure] IJX_RTCODE_BAGARG
//                  IJX_RTCODE_ERROR
//                  IJX_RTCODE_F_INSUFFICIENTBUF
//                  IJX_RTCODE_E_ERRPARAM
//                  IJX_RTCODE_F_NOTSUPPORTEDIDENT   
//                  IJX_RTCODE_F_NOTSUPPORTEDMARKER
//                  IJX_RTCODE_E_NOTSUPPORTEDMARKER
//                  
******************************************************************************/
IJXRESULT ijParseTablesMisc(IJBITTREAMSTATE *pStream,
                            IJDECODESTATE *pDecodeState)
{
    int marker;
    int   nStatus;
    IJXRESULT rtCode;

    nStatus=0;

    rtCode=ijReadMarker(&marker, pStream);
    if (!IJX_SUCCEEDED(rtCode)){
        return rtCode;
    }

    /* Parse APP0 */
    do{
        switch (marker) {
            //case IJX_MARKER_SOI:
            //    break;
            case IJX_MARKER_DHP:
                return IJX_RTCODE_E_NOTSUPPORTEDMARKER;
            case IJX_MARKER_EXP:
                return IJX_RTCODE_E_NOTSUPPORTEDMARKER;
            case IJX_MARKER_DAC:
                return IJX_RTCODE_E_NOTSUPPORTEDMARKER;
            case IJX_MARKER_DQT:
                rtCode=ijRead_DQT(pDecodeState->dctDequantTable,
                                  IJX_MAXDEQTTABLES,
                                  pStream);
                if (!IJX_SUCCEEDED(rtCode)){
                    return rtCode;
                }
                break;
            case IJX_MARKER_DHT:
                rtCode=ijRead_DHT( pDecodeState->dcHuffTable,
                                   pDecodeState->acHuffTable,
                                   IJX_MAXDEHUFFTABLES,
                                   pStream );
                if (!IJX_SUCCEEDED(rtCode)){
                    return rtCode;
                }
                break;
            case IJX_MARKER_DNL:
                return IJX_RTCODE_E_ERRPARSE;
            case IJX_MARKER_DRI:
                rtCode=ijRead_DRI( &(pDecodeState->nRstInterval),
                                     pStream );
                if (!IJX_SUCCEEDED(rtCode)){
                    return rtCode;
                }
                break;
            case IJX_MARKER_COM:
                rtCode=ijSkipMarker(pStream);
                if (!IJX_SUCCEEDED(rtCode)){
                    return rtCode;
                }
                break;
            case IJX_MARKER_APP0:
                rtCode=ijParseApp0(pStream,pDecodeState);
                if (!IJX_SUCCEEDED(rtCode)){
                    if (IJX_RTCODE_W_NOTSUPPORTEDIDENT!=rtCode) {
                        return rtCode;
                    }
                } 
                break;
            case IJX_MARKER_APP1:
            case IJX_MARKER_APP2:
            case IJX_MARKER_APP3:
            case IJX_MARKER_APP4:
            case IJX_MARKER_APP5:
            case IJX_MARKER_APP6:
            case IJX_MARKER_APP7:
            case IJX_MARKER_APP8:
            case IJX_MARKER_APP9:
            case IJX_MARKER_APP10:
            case IJX_MARKER_APP11:
            case IJX_MARKER_APP12:
            case IJX_MARKER_APP13:
            case IJX_MARKER_APP14:
                rtCode=ijSkipMarker(pStream);
                if (!IJX_SUCCEEDED(rtCode)){
                     return rtCode;
                } 
                break;
            case IJX_MARKER_SOF0:
                pDecodeState->frameSpec.nPrecision=8;
                pDecodeState->frameSpec.nSOF=IJX_MARKER_SOF0;
                pDecodeState->nLastMarker=IJX_MARKER_SOF0;
                return IJX_RTCODE_OK;
            case IJX_MARKER_SOF2:
                pDecodeState->frameSpec.nPrecision=8;
                pDecodeState->frameSpec.nSOF=IJX_MARKER_SOF2;
                pDecodeState->nLastMarker=IJX_MARKER_SOF2;
                return IJX_RTCODE_OK;
            case IJX_MARKER_SOFT:
                rtCode=ijGetTimeStamp(&(pDecodeState->timeSpec), pStream);
                if (!IJX_SUCCEEDED(rtCode)){
                    return rtCode;
                } 
                break;
            case IJX_MARKER_SOFS:
            case IJX_MARKER_SOFW:
                return IJX_RTCODE_E_WAVEMARKER;
            case IJX_MARKER_SOFV:
                pDecodeState->frameSpec.nPrecision=8;
                pDecodeState->frameSpec.nSOF=IJX_MARKER_SOFV;
                pDecodeState->nLastMarker=IJX_MARKER_SOFV;
                return IJX_RTCODE_OK;
            case IJX_MARKER_SOF1:
            case IJX_MARKER_SOF3:
            case IJX_MARKER_SOF6:
            case IJX_MARKER_SOF7:
            case IJX_MARKER_SOF8:
            case IJX_MARKER_SOF9:
            case IJX_MARKER_SOFA:
            case IJX_MARKER_SOFB:
            case IJX_MARKER_SOFD:
            case IJX_MARKER_SOFE:
            case IJX_MARKER_SOFF:
                return IJX_RTCODE_E_NOTSUPPORTEDMARKER;
            case IJX_MARKER_EOI:
                pDecodeState->nLastMarker=IJX_MARKER_EOI;
                return IJX_RTCODE_S_EOF;
            case IJX_MARKER_SOS:
                pDecodeState->nLastMarker=IJX_MARKER_SOS;
                return IJX_RTCODE_OK;
            default:
                pDecodeState->nLastMarker=marker;
                return IJX_RTCODE_W_NOTSUPPORTEDMARKER;
        }

        rtCode=ijReadMarker(&marker, pStream);

    } while(IJX_SUCCEEDED(rtCode));

    return IJX_RTCODE_ERROR;
}

/******************************************************************************
// Name:            ijPreprocessMarker
// Description:     Preprocess markers.
// Input Arguments:
//         pStream: Identifies IJBITTREAMSTATE data structure.
//    pDecodeState: Identifies IJDECODESTATE strcuture.
// Output Arguments:
//                     
//                  
******************************************************************************/
IJXRESULT ijPreprocessMarker(IJBITTREAMSTATE *pStream,
                             IJDECODESTATE *pDecodeState)

{
    IJXRESULT rtCode=IJX_RTCODE_E_ERRPARSE;

    switch (pDecodeState->nLastMarker) {
        case IJX_MARKER_SOF0:
        case IJX_MARKER_SOF2:
            rtCode=ijRead_SOF( &(pDecodeState->frameSpec),
                           pDecodeState->compSpec,
                           pStream );
            if (!IJX_SUCCEEDED(rtCode)) {
                return IJX_RTCODE_E_ERRPARSE;
            }
            pDecodeState->nDesiredMarker=IJX_MARKER_SOS;
            rtCode=ijInitFrameSpecInv(pDecodeState->nDesiredImageMode, 
                                      pStream,pDecodeState);
            if (!IJX_SUCCEEDED(rtCode)) {
                return rtCode;
            }
            break;
        case IJX_MARKER_SOFV:
            if (IJX_STATUS_FRAME&pDecodeState->nStatus) {
                ijInitMitionFrameInv(pStream,pDecodeState);
                rtCode=IJX_RTCODE_OK;
            } else {
                rtCode=ijInitFrameSpecInv(pDecodeState->nDesiredImageMode, 
                                          pStream,pDecodeState);
                pDecodeState->nStatus|=IJX_STATUS_FRAME;
            }
            pDecodeState->nDesiredMarker=IJX_MARKER_NONE;
            break;
        case IJX_MARKER_SOS:
            rtCode=ijRead_SOS( &(pDecodeState->scanSpec),
                               pDecodeState->compSpec,
                               pStream );
            if (!IJX_SUCCEEDED(rtCode)) {
                return IJX_RTCODE_E_ERRPARSE;
            }

            rtCode=ijInitScanSpecInv(pStream, pDecodeState);
            if (!IJX_SUCCEEDED(rtCode)) {
                return rtCode;
            }
            break;
        default:
            break;
    }

    pDecodeState->nLastMarker=IJX_MARKER_NONE;
    return rtCode;
}

/******************************************************************************
// Name:            ijAdjustRestartIntervalInv
// Description:     Process restart interval for decoding
// Input Arguments:
//         pStream: Identifies IJBITTREAMSTATE data structure.
//    pDecodeState: Identifies IJDECODESTATE strcuture.
// Output Arguments:
//                     
//                  
******************************************************************************/
IJXRESULT ijAdjustRestartIntervalInv(IJBITTREAMSTATE *pStream,
                                IJDECODESTATE *pDecodeState)
{
    IJXRESULT rtCode;

    pDecodeState->dcPred[0]=0;
    pDecodeState->dcPred[1]=0;
    pDecodeState->dcPred[2]=0;
    pDecodeState->dcPred[3]=0;

    pStream->nNumValidPrefetchedBits=0;
    pStream->nPrefetchedBits=0;

    pDecodeState->counter.nDRICounter=pDecodeState->nRstInterval;

    if (0!=pDecodeState->progSpec.nEOBRun) {
        return IJX_RTCODE_E_ERRPARSE;
    }

    /* Read RST marker */
    rtCode=ijReadMarker(&(pDecodeState->nLastMarker), pStream);
    if (!IJX_SUCCEEDED(rtCode)) {
        return IJX_RTCODE_E_ERRPARSE;
    }

    if ((IJX_MARKER_RST0<=pDecodeState->nLastMarker)&&
        (IJX_MARKER_RST7>=pDecodeState->nLastMarker)) {
        pDecodeState->nLastMarker=IJX_MARKER_NONE;
    }
    else {
        return IJX_RTCODE_E_ERRPARSE;
    }

    pDecodeState->counter.nRSTCounter=(pDecodeState->counter.nRSTCounter+1)&7;

    return IJX_RTCODE_OK;
}

/******************************************************************************
// Name:            ijCalcDecBufferSize
// Description:     Calculate buffer length for decoding
// Input Arguments:
//       nJPEGMode: Specifies JPEG mode
//        pMCUSpec: Points to IJMCUSPEC structure
// Output Arguments:
//      pIJXBuffer: Points to IJBUFFER structure
//                          
// Returns:          
//        [Success] IJX_RTCODE_OK
//        [Failure] IJX_RTCODE_BAGARG
//                  IJX_RTCODE_ERROR
//                     
//                  
******************************************************************************/
IJXRESULT ijCalcDecBufferSize(int         nJPEGMode,
                              int         nNumDesiredImageComp,
                              IJMCUSPEC   *pMCUSpec,
                              IJBUFFER    *pIJXBuffer)
{
    int nMCUDataTempBufLen, nFreqBufLen, nBlockCount;

    pIJXBuffer->paMCUCoeffBufCur[0]=pIJXBuffer->paMCUCoeffBuf[0]=NULL;                    
    pIJXBuffer->paMCUCoeffBufCur[1]=pIJXBuffer->paMCUCoeffBuf[1]=NULL;
    pIJXBuffer->paMCUCoeffBufCur[2]=pIJXBuffer->paMCUCoeffBuf[2]=NULL;
    pIJXBuffer->paMCUCoeffBufCur[3]=pIJXBuffer->paMCUCoeffBuf[3]=NULL;
    pIJXBuffer->paImgCoeffBufCur[0]=pIJXBuffer->paImgCoeffBuf[0]=NULL;                    
    pIJXBuffer->paImgCoeffBufCur[1]=pIJXBuffer->paImgCoeffBuf[1]=NULL;
    pIJXBuffer->paImgCoeffBufCur[2]=pIJXBuffer->paImgCoeffBuf[2]=NULL;
    pIJXBuffer->paImgCoeffBufCur[3]=pIJXBuffer->paImgCoeffBuf[3]=NULL;
    pIJXBuffer->nCoeffBufLen=0;

    pIJXBuffer->pAuxFreqBuf=NULL;
    pIJXBuffer->pAuxMCUDataTempBuf=NULL;
    pIJXBuffer->nAuxBufLen=0;

    pIJXBuffer->nMaxBufLen=0;

    nFreqBufLen=0;
    nBlockCount=0;

    if ((0<pMCUSpec->nMCUPadWidth)||(0<pMCUSpec->nMCUPadHeight)) {
        nMCUDataTempBufLen=(pMCUSpec->nMCUWidth*nNumDesiredImageComp)*pMCUSpec->nMCUHeight;
    } else {
        nMCUDataTempBufLen=0;
    }

    switch (nJPEGMode) {
        case IJX_MODE_BASELINE:
            pIJXBuffer->nFlag=IJX_JPEGBUFMODE_MCUORIMGCOEFF; //One MCU Coeff Buffer only
            nBlockCount=pMCUSpec->nBlksInMCU;
            break;
        case (IJX_MODE_BASELINE|IJX_MODE_MOTION_INDIV):
            pIJXBuffer->nFlag=IJX_JPEGBUFMODE_MCUORIMGCOEFF; //One MCU Coeff Buffer only
            nBlockCount=pMCUSpec->nBlksInMCU;
            break;

        case (IJX_MODE_BASELINE|IJX_MODE_MOTION_DIFF):
        case (IJX_MODE_BASELINE|IJX_MODE_MOTION_BRIEF):
            pIJXBuffer->nFlag=IJX_JPEGBUFMODE_MCUANDIMGCOEFF; //One MCU Coeff Buffer and One Img Coeff Buffer
            nBlockCount=(pMCUSpec->nTotalMCUCount+1)*pMCUSpec->nBlksInMCU;
            break;

        case IJX_MODE_PROGRESSIVE:
            pIJXBuffer->nFlag=IJX_JPEGBUFMODE_MCUANDIMGCOEFF; //One MCU Coeff Buffer only
            nBlockCount=(pMCUSpec->nTotalMCUCount+1)*pMCUSpec->nBlksInMCU;
            nFreqBufLen =(((257+7)*sizeof(int))*2)+31;
            break;

        case (IJX_MODE_PROGRESSIVE|IJX_MODE_MOTION_INDIV):
            pIJXBuffer->nFlag=IJX_JPEGBUFMODE_MCUIMGCOEFFSHARE; //One MCU Coeff Buffer shares One Img Coeff Buffer
            nBlockCount=(pMCUSpec->nTotalMCUCount)*pMCUSpec->nBlksInMCU;
            nFreqBufLen =(((257+7)*sizeof(int))*2)+31;
            break;
        case (IJX_MODE_PROGRESSIVE|IJX_MODE_MOTION_DIFF):
        case (IJX_MODE_PROGRESSIVE|IJX_MODE_MOTION_BRIEF):
            pIJXBuffer->nFlag=IJX_JPEGBUFMODE_MCUANDIMGCOEFF; //One MCU Coeff Buffer and One Img Coeff Buffer
            nBlockCount=(pMCUSpec->nTotalMCUCount+1)*pMCUSpec->nBlksInMCU;
            nFreqBufLen  =(((257+7)*sizeof(int))<<1)+31;
            break;

        case IJX_MODE_MOTION_INDIV:
            pIJXBuffer->nFlag=IJX_JPEGBUFMODE_MCUORIMGCOEFF; //One MCU Coeff Buffer only
            nBlockCount=pMCUSpec->nBlksInMCU;
            break;
        case IJX_MODE_MOTION_DIFF:
        case IJX_MODE_MOTION_BRIEF:
            pIJXBuffer->nFlag=IJX_JPEGBUFMODE_MCUANDIMGCOEFF; //One MCU Coeff Buffer and One Img Coeff Buffer
            nBlockCount=(pMCUSpec->nTotalMCUCount+1)*pMCUSpec->nBlksInMCU;
            break;
        default:
            return IJX_RTCODE_ERROR;
    }

    pIJXBuffer->nCoeffBufLen  = (nBlockCount<<6)*sizeof(Ipp16s)+31;

    pIJXBuffer->nAuxBufLen    = _IJX_MAX(nMCUDataTempBufLen,nFreqBufLen);
    if (pIJXBuffer->nAuxBufLen) pIJXBuffer->nAuxBufLen+=31;

    pIJXBuffer->nMaxBufLen    = (pIJXBuffer->nCoeffBufLen)+(pIJXBuffer->nAuxBufLen);

    return IJX_RTCODE_OK;
}

/******************************************************************************
// Name:            ijDecompress_BaseLine
// Description:     Decompress JPEG stream which was encoded in Baseline mode.
// Input Arguments:
//         pStream: Points to IJBITTREAMSTATE structure.
//      pIJXBuffer: Points to IJBUFFER structure
//                     
//                  
******************************************************************************/
IJXRESULT ijDecompress_BaseLine(IJBITTREAMSTATE *pStream,
                                IJDECODESTATE *pDecodeState)
{
    IJXRESULT rtCode;
	printf("ijDecompress_BaseLine\n");

    rtCode=ijDecodeScanData_Baseline(pStream, pDecodeState);
    if (!IJX_SUCCEEDED(rtCode)) {
        return rtCode;
    }
    
    
    if (0xD9!=pDecodeState->nLastMarker) {
        rtCode=ijReadMarker(&(pDecodeState->nLastMarker), pStream);    
        if (!IJX_SUCCEEDED(rtCode)) {
            return rtCode;
        }
    }

    if (IJX_MODE_MOTION_MASK&(pDecodeState->nJPEGCodeMode)) {
        pDecodeState->nJPEGCodeMode&=~IJX_MODE_STILL_MASK;
        if (IJX_MODE_MOTION_DIFF&pDecodeState->nJPEGCodeMode) {
            pDecodeState->procSpec.funcDecompress=(PFUNCODEC)ijDecompress_Motion_Diff;
        } else if (IJX_MODE_MOTION_BRIEF&pDecodeState->nJPEGCodeMode) {
            pDecodeState->procSpec.funcDecompress=(PFUNCODEC)ijDecompress_Motion_Brief;
        } else {
            pDecodeState->procSpec.funcDecompress=(PFUNCODEC)ijDecompress_Motion_Indiv;
        }
        pDecodeState->nDesiredMarker=IJX_MARKER_SOF;
        return IJX_RTCODE_S_CONTINUE;
    }

    return IJX_RTCODE_S_EOF;
}

/******************************************************************************
// Name:            ijDecompress_Progressive
// Description:     Decompress JPEG stream which was encoded in Progressive mode.
// Input Arguments:
//         pStream: Points to IJBITTREAMSTATE structure.
//      pIJXBuffer: Points to IJBUFFER structure
//                     
//                  
******************************************************************************/
IJXRESULT ijDecompress_Progressive(IJBITTREAMSTATE *pStream,
                                   IJDECODESTATE *pDecodeState)
{
    IJXRESULT rtStatus;
    IJXRESULT rtCode;

    rtStatus=IJX_RTCODE_S_CONTINUE;
    
    do{
        rtCode=ijParseTablesMisc(pStream, pDecodeState);
        if (!IJX_SUCCEEDED(rtCode)) {
            return rtCode;
        }

        if (IJX_RTCODE_S_EOF==rtCode) {
            if (IJX_OP_MULTIPLE!=pDecodeState->nOperationMode) {
                return IJX_RTCODE_S_EOF;
            }

            rtStatus=IJX_RTCODE_S_EOF;
            break;
        }

        rtCode=ijPreprocessMarker(pStream, pDecodeState);
        if (!IJX_SUCCEEDED(rtCode)) {
            return rtCode;
        }

        rtCode=ijDecodeScanData_Progressive(pStream, pDecodeState);
        if (!IJX_SUCCEEDED(rtCode)) {
            return rtCode;
        }

        pDecodeState->nDesiredMarker=IJX_MARKER_SOS;    

    } while (IJX_OP_MULTIPLE==pDecodeState->nOperationMode);

    ijIntiDecodeCoeff(pDecodeState);


    if (IJX_MODE_MOTION_MASK&(pDecodeState->nJPEGCodeMode)) {
        pDecodeState->nJPEGCodeMode&=~IJX_MODE_STILL_MASK;
        if (IJX_MODE_MOTION_DIFF&pDecodeState->nJPEGCodeMode) {
            pDecodeState->procSpec.funcDecompress=(PFUNCODEC)ijDecompress_Motion_Diff;
        } else if (IJX_MODE_MOTION_BRIEF&pDecodeState->nJPEGCodeMode) {
            pDecodeState->procSpec.funcDecompress=(PFUNCODEC)ijDecompress_Motion_Brief;
        } else {
            pDecodeState->procSpec.funcDecompress=(PFUNCODEC)ijDecompress_Motion_Indiv;
        }
        pDecodeState->nDesiredMarker=IJX_MARKER_SOF;
        return IJX_RTCODE_S_CONTINUE;
    }

    return rtStatus;
}

/******************************************************************************
// Name:            ijDecompress_Motion
// Description:     Decompress JPEG stream which was encoded in Motion JPEG mode.
// Input Arguments:
//         pStream: Points to IJBITTREAMSTATE structure.
//      pIJXBuffer: Points to IJBUFFER structure
//                     
//                  
******************************************************************************/
IJXRESULT ijDecompress_Motion_Indiv(IJBITTREAMSTATE *pStream,
                                    IJDECODESTATE *pDecodeState)
{
    IJXRESULT rtCode;

    rtCode=ijDecodeScanData_Motion(pStream, pDecodeState);

    if (!IJX_SUCCEEDED(rtCode)) {
        return rtCode;
    }

    pDecodeState->nDesiredMarker=IJX_MARKER_SOF;    

    //pDecodeState->counter.nFrameMCUCounter+=pDecodeState->counter.nScanMCUCounter;
    //pDecodeState->counter.nTotalMCUCounter+=pDecodeState->counter.nFrameMCUCounter;

    return IJX_RTCODE_S_CONTINUE;
}

/******************************************************************************
// Name:            ijDecompress_Motion_Diff
// Description:     Not supports in this version
// Input Arguments:
// Output Arguments:
//                   NONE       
// Returns:          
//                   NONE
//                     
//                  
******************************************************************************/

///////////////////////////////////////
#ifdef _MOTION_DIFF
IJXRESULT ijDecompress_Motion_Diff( IJBITTREAMSTATE *pStream,
                                    IJDECODESTATE *pDecodeState)
{
    IJXRESULT rtCode;

    if (IJX_MARKER_SOS==pDecodeState->nDesiredMarker) {
        rtCode=ijParseTablesMisc(pStream, pDecodeState);
        if (!IJX_SUCCEEDED(rtCode)) {
            return rtCode;
        }
        if (IJX_RTCODE_S_EOF==rtCode) {
           return IJX_RTCODE_S_EOF;
        }
        rtCode=ijPreprocessMarker(pStream, pDecodeState);
        if (!IJX_SUCCEEDED(rtCode)) {
            return rtCode;
        }
    }

    rtCode=ijDecodeScanData_Motion_Diff(pStream, pDecodeState);
    if (!IJX_SUCCEEDED(rtCode)) {
        return rtCode;
    }

    if (pDecodeState->procSpec.funcMotionDiffDecoder!=pDecodeState->procSpec.funcMotionDiffRefine) {
        pDecodeState->procSpec.funcMotionDiffDecoder=pDecodeState->procSpec.funcMotionDiffRefine;
    }

    pDecodeState->nDesiredMarker=IJX_MARKER_SOF;

    pDecodeState->counter.nFrameMCUCounter+=pDecodeState->counter.nScanMCUCounter;
    pDecodeState->counter.nTotalMCUCounter+=pDecodeState->counter.nFrameMCUCounter;

    return IJX_RTCODE_S_CONTINUE;
}
#endif
///////////////////////////////////////

/******************************************************************************
// Name:            ijDecompress_Motion_Diff
// Description:     Not supports in this version
// Input Arguments:
// Output Arguments:
//                   NONE       
// Returns:          
//                   NONE
//                     
//                  
******************************************************************************/
///////////////////////////////////////
#ifdef _MOTION_BRIEF
IJXRESULT ijDecompress_Motion_Brief(IJBITTREAMSTATE *pStream,
                                    IJDECODESTATE *pDecodeState)
{
    IJXRESULT rtCode;

    if (IJX_MARKER_SOS==pDecodeState->nDesiredMarker) {
        rtCode=ijParseTablesMisc(pStream, pDecodeState);
        if (!IJX_SUCCEEDED(rtCode)) {
            return rtCode;
        }
        if (IJX_RTCODE_S_EOF==rtCode) {
           return IJX_RTCODE_S_EOF;
        }
        rtCode=ijPreprocessMarker(pStream, pDecodeState);
        if (!IJX_SUCCEEDED(rtCode)) {
            return rtCode;
        }
    }

    rtCode=ijDecodeScanData_Motion_Diff(pStream, pDecodeState);
    if (!IJX_SUCCEEDED(rtCode)) {
        return rtCode;
    }

    if (pDecodeState->procSpec.funcMotionDiffDecoder!=pDecodeState->procSpec.funcMotionDiffRefine) {
        pDecodeState->procSpec.funcMotionDiffDecoder=pDecodeState->procSpec.funcMotionDiffRefine;
    }

    pDecodeState->nDesiredMarker=IJX_MARKER_SOF;

    pDecodeState->counter.nFrameMCUCounter+=pDecodeState->counter.nScanMCUCounter;
    pDecodeState->counter.nTotalMCUCounter+=pDecodeState->counter.nFrameMCUCounter;

    return IJX_RTCODE_S_CONTINUE;
}
#endif
///////////////////////////////////////

/* EOF */

